package core
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.FileListEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.FileFilter;
	import flash.net.SharedObject;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.Security;
	import flash.utils.ByteArray;

	import mx.controls.Alert;
	import mx.events.FileEvent;
	import mx.events.MenuEvent;
	import mx.managers.PopUpManager;

	import rpg.data.ResData;
	import rpg.resource.*;

	import spark.components.TitleWindow;

	import view.CreateMapView;
	import view.ResourceTree;


	public class MenuController
	{
		private static var instance : MenuController;
		private var resClassArray : Array;
		private var so : SharedObject;

		public function MenuController()
		{
			so = SharedObject.getLocal("mapEditor");
		}

		public static function getInstance() : MenuController
		{
			if(instance == null)
				instance = new MenuController();
			return instance;
		}

		[Binable]
		public var menubarXML : XMLList =
			<>
				<menuitem label="操作" data="top">
					<menuitem label="新建" data="createMap"/>
					<menuitem label="打开" data="open"/>
					<menuitem label="导入资源" data="importRes"/>
				</menuitem>
				<menuitem label="保存" data="top">
					<menuitem label="保存资源" data="saveFile"/>
					<menuitem label="生成小地图" data="saveMinMap"/>
				</menuitem>
			</>;

		public function itemClickHandler(event : MenuEvent) : void
		{
			var swfFile : File;
			var txtFilter : FileFilter;

			switch(String(event.item.@data))
			{
				case "importRes":
					swfFile = new File();
					txtFilter = new FileFilter("swf文件(.swf)", "*.swf");
					swfFile.browseForOpenMultiple("选择要导入的文件", [txtFilter]);
					swfFile.addEventListener(FileListEvent.SELECT_MULTIPLE, swfFileSelectedHandler);
					break;
				case "createMap":
					TitleWindow(PopUpManager.createPopUp(Config.stage, CreateMapView, true));
					break;
				case "saveFile":
					var saveFile : File = new File();
					saveFile.browseForSave("保存文件");
					saveFile.addEventListener(Event.SELECT, saveFileHandler);
					break;
				case "open":
					swfFile = new File();
					if(so.data["openUrl"])
					{
						swfFile.nativePath = so.data["openUrl"];
					}
					txtFilter = new FileFilter("地图(.map)", "*.map");
					swfFile.browseForOpen("选择要导入的地图", [txtFilter]);
					swfFile.addEventListener(Event.SELECT, openMapFileHandler);
					break;
				case "saveMinMap":
					saveFile = new File();
					saveFile.browseForSave("生成地图");
					saveFile.addEventListener(Event.SELECT, saveMinMapHandler);
					break;
			}
		}

		private function saveMinMapHandler(evt : Event) : void
		{
			var saveFile : File = evt.currentTarget as File;
			var nativePath : String = saveFile.nativePath;

			if(nativePath.indexOf(".jpg") == -1)
			{
				nativePath = nativePath + ".jpg";
			}
			FilesUtil.saveBmp(MapController.getInstance().getSaveMapBitmapData(), nativePath, FilesUtil.JPG);
			Alert.show("生成成功!", "提示");
		}

		/**
		 * 导入地图文件
		 * @param evt
		 *
		 */
		private function openMapFileHandler(evt : Event) : void
		{
			var saveFile : File = evt.currentTarget as File;
			var bytes : ByteArray = FilesUtil.getBytesFromeFile(saveFile.nativePath, true);
			var tmpMapdata : Object = bytes.readObject();

			so.setProperty("openUrl", saveFile.nativePath);
			so.flush();

			Config.mapCols = int(tmpMapdata.mapCols);
			Config.mapRows = int(tmpMapdata.mapRows);
			Config.tileWidth = int(tmpMapdata.tileWidth);
			Config.tileHeight = int(tmpMapdata.tileHeight);
			Config.mapID = tmpMapdata.mapID;

			if(tmpMapdata.resUrl is Array)
			{
				Config.resUrl = tmpMapdata.resUrl;
			}
			else
			{
				Config.resUrl = [tmpMapdata.resUrl];
			}
			Config.mapBgUrl = tmpMapdata.mapBgUrl;

			MapController.getInstance().createMap();
			MapController.getInstance().updateMapData();

			var mapData : MapData = MapController.getInstance().mapData;
			var dataArray : Array = tmpMapdata.data as Array;
			var len : int = dataArray.length;

			for(var col : int = 0; col < len; col++)
			{
				for(var row : String in dataArray[col])
				{
					var data : Object = dataArray[col][row];
					var node : Node = mapData.data[col][row];

					if(row == "0")
					{
						data = dataArray[col][Config.mapRows - 1];
					}

					if(data == null)
						continue;
					Config.readObject(node, data);
				}
			}

			resClassArray = [];
			loadIndex = 0;

			for each(var key : String in Config.resUrl)
			{
				var swfBytes : ByteArray = bytes.readObject();
				this.loaderSwfFileByByteArray(swfBytes);
			}
			var hasBgImage : Boolean = bytes.readBoolean();

			if(hasBgImage)
			{
				var bgImageBytes : ByteArray = bytes.readObject();
				MapController.getInstance().bgImagBytes = bgImageBytes;
				bgImageBytes.position = 0;
				var loader : Loader = new Loader();
				loader.loadBytes(bgImageBytes);
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBgComplete);
			}

			if(bytes.bytesAvailable)
			{
				var mapOtherElements : Array = bytes.readObject();
				len = mapOtherElements.length;
				trace("地图移动元素:", mapOtherElements.length);
			}
		}

		/**
		 * 背景图片加载完成
		 * @param evt
		 *
		 */
		private function onBgComplete(evt : Event) : void
		{
			if(evt.target.content is Bitmap)
			{
				MapController.getInstance().bitmapData = Bitmap(evt.target.content).bitmapData;
			}
		}

		/**
		 * 保存文件称.map
		 * @param evt
		 *
		 */
		private function saveFileHandler(evt : Event) : void
		{
			var mapController : MapController = MapController.getInstance();
			var saveFile : File = evt.currentTarget as File;
			var bytes : ByteArray = new ByteArray();
			mapController.updateMapData();

			var id : String = saveFile.name.replace(".txt", "");

			var mapData : MapData = mapController.mapData;
			mapData.id = id;
			bytes.writeObject(getMapData(mapData));

			for each(var byte : ByteArray in Config.swfBytes)
			{
				bytes.writeObject(byte);
			}

			var hasBg : Boolean = mapController.bgImagBytes != null;
			bytes.writeBoolean(hasBg);

			if(mapController.bgImagBytes)
			{
				bytes.writeObject(mapController.bgImagBytes);
			}

			var mapOtherElements : Array = getMapOtherElement(mapData);
			bytes.writeObject(mapOtherElements);
			trace("地图移动元素:", mapOtherElements.length);

			var url : String = saveFile.nativePath;

			if(url.indexOf(".map") < 0)
			{
				FilesUtil.saveToFile(url + ".map", bytes, true, true);
			}

			var clientBytes : ByteArray = new ByteArray();
			clientBytes.writeObject(MapController.getInstance().mapData);
			clientBytes.writeObject(mapOtherElements);
			url = saveFile.nativePath;

			//服务器数据
			saveToServerConfig(url, id);

			if(url.indexOf(".mapx") < 0)
				FilesUtil.saveToFile(url + ".mapx", clientBytes, true, true);
			//------------------------------------------------------

			Alert.show("保存成功!地址：" + url);
		}

		/**
		 * 克隆一个可以保存的地图元素
		 * @param data
		 * @return
		 *
		 */
		private function getMapData(data : MapData) : Object
		{
			var clone : Object = new Object();
			clone.mapCols = int(data.mapCols);
			clone.mapRows = int(data.mapRows);
			clone.tileWidth = int(data.tileWidth);
			clone.tileHeight = int(data.tileHeight);
			clone.mapID = data.mapID;
			clone.resUrl = data.resUrl;
			clone.mapBgUrl = data.mapBgUrl;
			clone.data = [];

			for(var col : int = 0; col < Config.mapCols; col++)
			{
				clone.data.push([]);

				for(var row : int = 0; row < Config.mapRows; row++)
				{
					var node : Node = data.data[col][row];

					if(node.type == Config.air && node.otherData.length == 0)
						continue;
					clone.data[col][row] = Config.clone(node);
				}
			}
			return clone;
		}

		/**
		 * 获得地图上其他元素
		 * @return
		 *
		 */
		private function getMapOtherElement(data : MapData) : Array
		{
			var elements : Array = [];

			for(var col : int = 0; col < Config.mapCols; col++)
			{
				for(var row : int = 0; row < Config.mapRows; row++)
				{
					var node : Node = data.data[col][row];

					if(node && node.otherData.length >= 0)
					{
						elements = elements.concat(node.otherData);
					}
				}
			}
			return elements;
		}

		/**
		 * 保存成服务器配置
		 *
		 */
		private function saveToServerConfig(url : String, id : String) : void
		{
			var mapData : MapData = MapController.getInstance().mapData;
			var tileWidth : int = mapData.tileWidth;
			var tileHeigth : int = mapData.tileHeight;
			var rows : int = mapData.mapRows;
			var cols : int = mapData.mapCols;
			var mapArr : Array = mapData.data;
			var mapDataTxt : String = "[{id,";
			mapDataTxt += id;
			mapDataTxt += "},{width,";
			mapDataTxt += tileWidth;
			mapDataTxt += "},{height,";
			mapDataTxt += tileHeigth;
			mapDataTxt += "},{mask,\r\n\"";
			var tileCount : int = 0;
			var depth : String = "\r\n,{depth,\"";
			var otherElement : String = "\r\n,{element,[";

			for(var row : int = 0; row < rows; row++)
			{
				for(var col : int = 0; col < cols; col++)
				{
					var node : Node = mapArr[col][row] as Node;

					if(node == null || (row == Config.air && node.type == Config.groundType))
					{
						mapDataTxt += "0";
						depth += "0";
					}
					else
					{
						mapDataTxt += String(node.type);

						//保存时，空白，梯子下端，和中间。强制改成0
						if(node.type == Config.air || node.type == Config.ladderDown || node.type == Config.ladderNormal)
						{
							depth += "0";
						}
						else
						{
							depth += String(node.groundHardness);
						}

						if(node.type == 1)
						{
							tileCount++;
						}
					}

					if(node && node.otherData.length > 0)
					{
						for each(var mapElement : MapElement in node.otherData)
						{
							if(otherElement != "\r\n,{element,[")
								otherElement += "\r\n,";
							otherElement += mapElement.toServerString();
						}
					}
				}

				if(row == rows - 1)
				{
					break;
				}
				mapDataTxt += "\r\n";
				depth += "\r\n";
			}
			depth += "\"}";
			otherElement += "]}\r\n";

			mapDataTxt += "\"},{brick_num," + tileCount + "}";
			mapDataTxt += depth;
			mapDataTxt += otherElement;
			mapDataTxt += "]";

			if(url.indexOf(".txt") < 0)
				FilesUtil.saveUTFBytesToFile(url + ".txt", mapDataTxt);
		}

		/**
		 * 导入的资源文件
		 * @param evt
		 *
		 */
		private var loadIndex : int;

		private function swfFileSelectedHandler(evt : FileListEvent) : void
		{
			Config.resUrl = [];
			Config.swfBytes = [];
			resClassArray = [];
			loadIndex = 0;

			for each(var swfFile : File in evt.files)
			{
				Config.resUrl.push(swfFile.name);
				var bytes : ByteArray = FilesUtil.getBytesFromeFile(swfFile.nativePath);
				loaderSwfFileByByteArray(bytes);
			}
		}

		private function loaderSwfFileByByteArray(bytes : ByteArray) : void
		{
			var loader : Loader = new Loader();
			var lc : LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
			Config.appDomain = ApplicationDomain.currentDomain;
			Config.swfBytes.push(bytes);
			lc.allowCodeImport = true;
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onResComplete);
			loader.contentLoaderInfo.addEventListener("securityError", onSecurityError);
			loader.loadBytes(bytes, lc);
		}

		private function onSecurityError(evt : Event) : void
		{

		}

		private function onResComplete(evt : Event) : void
		{
			var loaderInfo : LoaderInfo = evt.currentTarget as LoaderInfo;
			var bytes : ByteArray = loaderInfo.bytes;
			parseSwf(bytes);
			loadIndex++;

			if(loadIndex == Config.resUrl.length)
				MapController.getInstance().createMapByMapData();
		}

		private function parseSwf(bytes : ByteArray) : void
		{
			var classArray : Array = GetSwfAllClass.getSWFClassName(bytes);
			classArray.sort(Array.UNIQUESORT);
			resClassArray = resClassArray.concat(classArray);
			ResourceTree.classArray = resClassArray;
			EventManager.getInstance().dispatchListener(EventManager.EVENT_RES_COMPLETE);
		}
	}
}